#!/usr/bin/python
#-*- coding: utf-8 -*-
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import sys,os
from math import *
import Image
from numpy import *
from OpenGL.arrays import vbo
import time
from mymath import *
from mygl import *

# Eigene Module
from vbo_handler import *
from gameobjects import Skybox
from gameobjects.marble_run import *
from GameConfigFile import *
from ShaderWrapper import *
from BSpline import *
frameCam = GLFrame()

counter = [0,0,0]   # Liste der Murmelnummern
animiert = False    # Anzahl aktiver Murmeln 
mouse_clicked = False
camera_position = 0

angleX = 0
angleY = 0
angleZ = 0

scale_factor = 1.0

old_x = 0
old_y = 0

skybox = None
sphere = None
marble_run = None


def display():    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()

    glScale(2, 2, 2)

    glRotate(angleX, 1, 0, 0)
    glRotate(angleY, 0, 1, 0)
    glRotate(angleZ, 0, 0, 1)

    set_camera_origin()
        
    frameCam.ApplyCameraTransform()

    skybox.draw_skybox()

    sw.use_shader_program()
    marble_run.draw()
    sw.kill_shader_program()    

    # Erzeugen der Murmeln
    for i in range(animiert):
        glPushMatrix()
        glTranslate(coordinates[counter[i]][0],
                    coordinates[counter[i]][1]+MARBLE_RADIUS, #Damit Murmel auf Bahn ist
                    coordinates[counter[i]][2])
        gluSphere(gluNewQuadric(), MARBLE_RADIUS, MARBLE_DETAIL, MARBLE_DETAIL)
        glPopMatrix()

    glutSwapBuffers()


def set_camera_origin():
    global camera_position
    """Setzt den Ursprungspunkt der Kamera"""
    if camera_position == 0:
        frameCam.setOrigin((CUBE_SIZE/2)-1, (CUBE_SIZE/2)-1, (CUBE_SIZE/2)-1)
        camera_position = -1
    elif camera_position >= 1:
        if camera_position-1 >= animiert:
            camera_position = -1
            return
        frameCam.setOrigin(coordinates[counter[camera_position-1]][0],
                           coordinates[counter[camera_position-1]][1]+MARBLE_RADIUS*4,
                           coordinates[counter[camera_position-1]][2])


def reshape(w,h):
    if h == 0:
        h = 1
    glViewport(0,0,w,h)
    aspect = float(w) / float(h)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45.0,aspect,0.1,100.0)
    glMatrixMode(GL_MODELVIEW)
    glutSwapBuffers()


def mousemoved(x,y):
    global angleX, angleY, old_x, old_y, mouse_clicked
    if not mouse_clicked:
        angleY -= (old_x -x)*SENSITIVITY
        angleX -= (old_y -y)*SENSITIVITY
    old_x = x
    old_y = y
    mouse_clicked = False
    glutPostRedisplay()

def mouse(button, state, x, y):
    global mouse_clicked
    if state == GLUT_DOWN:
       mouse_clicked = True


def keypressed(key,x,y):
    global animiert, counter, camera_position, angleX, angleY, angleZ, scale_factor
    if key == '+':
        animiert += 1
        if animiert >= 4:
            animiert = 0
            counter = [0,0,0]

    if key == '-':
        animiert -= 1
        if animiert < 0:
            animiert = 0

    elif key == '0':
        camera_position = 0
    elif key == '1':
        camera_position = 1
    elif key == '2':
        camera_position = 2
    elif key == '3':
        camera_position = 3
    elif key == '4':
        angleY -= CAMERA_STEPS
    elif key == '5':
        angleX -= CAMERA_STEPS
    elif key == '6':
        angleY += CAMERA_STEPS
    elif key == '7':
        angleZ += CAMERA_STEPS
    elif key == '8':
        angleX += CAMERA_STEPS
    elif key == '9':
        angleZ -= CAMERA_STEPS
    glutPostRedisplay()


def animate():
    global angle, counter
    if animiert:
        for i in range(animiert):
            counter[i] += 1
            if counter[i] >= len(coordinates):
                counter[i] = 0
            glutPostRedisplay()
        time.sleep(TIME_SLEEP)
 
 
def main():    
    global skybox, sphere, marble_run, sw, coordinates
    skybox = Skybox.Skybox()
   
    # Einlesen der Shader
    sw = ShaderWrapper(MARBLE_RUN_SHADER)
    
    # Einlesen der Koordinaten
    bspline = BSpline()
    bspline.scale_data()
    coordinates = bspline.calculate_points(POINT_STEPS)
    
    # Erzeugen der Murmelbahn
    marble_run =  MarbleRun(coordinates)
    
   
    # Standard-Kram
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
    
    glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT)
    glutCreateWindow("Skybox")
    glutDisplayFunc(display)
    glutReshapeFunc(reshape)
    glutKeyboardFunc(keypressed)
    glutMotionFunc(mousemoved)
    glutIdleFunc(animate)
    glutMouseFunc(mouse)
    
    #Shader-Dinge
    sw.init_vertex_shader()
    sw.init_fragment_shader()
    sw.link_shaders()

    # skybox initialsieren
    glEnable(GL_DEPTH_TEST)
    skybox.init_skybox()
    glutMainLoop()
    
if __name__=='__main__':
    main()
